#include <stdio.h>
#include <stdint.h>
#include <stdlib.h>
#include <string.h>

#ifndef __SIZE_T
#define __SIZE_T
typedef unsigned int size_t;
#endif

int main(int argc, char **argv) 
{
    //malloc函数
    int *pi = (int*) malloc(sizeof(int));
    //执行malloc函数会进行以下操作
    //1.从堆上分配内存
    //2.内存不会被修改或是清空
    //3.返回首字节的地址

    int *p = (int*) malloc(sizeof(int));
    printf("Address of pi: %d And Value of pi: %d\n", pi,*pi);
    printf("Address of p: %d And Value of p: %d\n", p,*p);

    //char *name;
    char *name = (int*) malloc(sizeof(int));
    printf("Enter a name:");
    scanf("%s", name);
    printf("Your name is : %s\n", name);

    //要给malloc传递正确的参数
    //给10个双精度浮点数分配空间
    const int NUMBER_OF_DOUBLES = 10;
    double *pd = (double*) malloc(NUMBER_OF_DOUBLES * sizeof(double));

    //没有标准的方法可以知道堆上分配的内存总数

    //使用calloc函数
    //calloc会在分配的同时清空内存
    //void *calloc(size_t numElements, size_t emementSize);
    int *p1 = calloc(5, sizeof(int));   //分配全部为0的20字节

    int *p2 = malloc(5 * sizeof(int));  //同上
    memset(p2, 0, 5 * sizeof(int));

    //使用relloc函数，重新分配内存
    //void *realloc(void *ptr, size_t size);
    char *string1;
    char *string2;
    string1 = (char*) malloc(16);
    strcpy(string1, "0123456789AB");
    string2 = realloc(string1, 8);
    printf("string1 Value: %p [%s]\n", string1, string1);
    printf("string2 Value: %p [%s]\n", string2, string2);

    string2 = realloc(string1, 64);
    printf("string1 Value: %p [%s]\n", string1, string1);
    printf("string2 Value: %p [%s]\n", string2, string2)
    ;

    //用free函数释放内存，void free(void *ptr);
    free(pi);
    free(name);
    free(p);
    free(pd);
    free(p1);
    free(p2);
    free(string2);

    //重复释放
    //两个指针引用同一个地址称为别名
    int *p3 = (int*) malloc(sizeof(int));
    int *p4 = p3;
    free(p3);
    //free(p4);
    //free(string1);

    //堆和系统内存

    //程序结束前释放内存
    //操作系统负责维护应用程序的资源，包括内存
    //当程序终止时，操作系统要负责重新分配这块内存以便别的应用程序使用
    //是否要在程序终止前释放内存取决于具体的应用程序

    //迷途指针
    //如果内存已经释放，而指针还在引用原始内存，这样的指针就称为迷途指针，迷途指针没有指向有效对象，有时候也称为过早释放

    //处理迷途指针

    //调试器对检测内存泄露的支持
    //微软的支持:https://docs.microsoft.com/zh-cn/visualstudio/debugger/finding-memory-leaks-using-the-crt-library?view=vs-2015
    //gcc的支持Mudflap库：

    //c的垃圾回收
    //malloc和free是手动分配和释放内存
    //Boehm-Weiser Collector， c 和 c++的垃圾回收器
    


    return 0;
}
